package console4.widgets;

import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;


public class ConsoleTab extends CTabItem {
	private ConsoleTextPane consoleTextPane;
	private ConsoleTextPrompt consoleTextPrompt;
	private File currentPath=new File("C:\\");
	private Label consoleCurrentPathLabel;
	private static final Pattern CD_PATTERN=Pattern.compile("cd\\s+\"?(.*)\"?\\s*");

	public ConsoleTab(CTabFolder tabbedFolder, String title) throws IOException {
		super(tabbedFolder,SWT.CLOSE);
		this.setText(title);
		{
			Composite composite=new Composite(tabbedFolder, SWT.NONE);
			this.setControl(composite);
			composite.setLayout(new FormLayout());
			
			DropTarget target = new DropTarget(composite, DND.DROP_DEFAULT | DND.DROP_MOVE);
			target.setTransfer(new Transfer[] {TextTransfer.getInstance(),FileTransfer.getInstance()});
			target.addDropListener(new DropTargetAdapter() {
				@Override
				public void drop(DropTargetEvent event) {
					if(event.data instanceof String[])
						consoleTextPrompt.appendPath(((String[])event.data)[0]);
					else if(event.data instanceof File[])
						consoleTextPrompt.appendPath(((File[])event.data)[0].getAbsolutePath());
				}
			});
			
			consoleTextPane = new ConsoleTextPane(composite);
			consoleCurrentPathLabel = new Label(composite, SWT.NONE);
			consoleCurrentPathLabel.setText(currentPath.getAbsolutePath()+" >");
			consoleTextPrompt = new ConsoleTextPrompt(composite,this);
			
			FormData consoleTextPaneLayoutData = new FormData();
			consoleTextPaneLayoutData.top=new FormAttachment(0);
			consoleTextPaneLayoutData.left=new FormAttachment(0);
			consoleTextPaneLayoutData.right=new FormAttachment(100);
			consoleTextPaneLayoutData.bottom=new FormAttachment(consoleCurrentPathLabel,-2);
			consoleTextPane.setLayoutData(consoleTextPaneLayoutData);
			
			FormData consoleCurrentPathLayoutData = new FormData();
			consoleCurrentPathLayoutData.left=new FormAttachment(0);
			consoleCurrentPathLayoutData.right=new FormAttachment(100);
			consoleCurrentPathLayoutData.bottom=new FormAttachment(consoleTextPrompt.getComponent(),-2);
			consoleCurrentPathLabel.setLayoutData(consoleCurrentPathLayoutData);
			
			FormData consoleTextPromptLayoutData = new FormData();
			consoleTextPromptLayoutData.left=new FormAttachment(0);
			consoleTextPromptLayoutData.right=new FormAttachment(100);
			consoleTextPromptLayoutData.bottom=new FormAttachment(100);
			consoleTextPrompt.setLayoutData(consoleTextPromptLayoutData);
		}
	}

	public ConsoleTab(CTabFolder tabbedFolder, String string, TabSaveState tss) throws IOException {
		this(tabbedFolder, string);
		consoleTextPane.setOldText(tss);
		consoleTextPrompt.setOldCommands(tss.getOldCommands());
		this.setPath(tss.getCurrentPath());
	}

	public void resetFocus() {
		consoleTextPrompt.getComponent().setFocus();
	}

	public TabSaveState createSaveState() {
		return new TabSaveState(consoleTextPane.getText(),consoleTextPane.getTextLayout(),consoleTextPrompt.getOldCommands(),currentPath);
	}

	public void execute(String text) {
		try {			
			Matcher cdMatcher=CD_PATTERN.matcher(text);
			if(cdMatcher.matches()) {
				File newAbsPath = new File(cdMatcher.group(1));
				
				if(newAbsPath.isAbsolute()) {
					if(newAbsPath.exists() && newAbsPath.isDirectory())
						setPath(newAbsPath);
					else {
						consoleTextPane.addTextToPane("⋙ ", false);
						consoleTextPane.addTextToPane("The Directory \""+newAbsPath.getAbsolutePath()+"\" does not exist.\n",true);
					}
				}
				else {
					File newRelPath=new File(currentPath,cdMatcher.group(1));
					if(newRelPath.exists() && newRelPath.isDirectory())
						setPath(newRelPath);
					else {
						consoleTextPane.addTextToPane("⋙ ", false);
						consoleTextPane.addTextToPane("The Directory \""+newRelPath.getAbsolutePath()+"\" does not exist.\n",true);
					}
				}
			}
			else {
				consoleTextPane.addTextToPane("⋙ ", false);
				ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe","/C",text); 
				processBuilder.directory(currentPath);
			    Process console = processBuilder.start();
			    
				consoleTextPane.setConsoleOutput(console.getInputStream());
				consoleTextPane.setConsoleErrorOutput(console.getErrorStream());
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	private void setPath(File newPath) throws IOException {
		this.currentPath=newPath.getCanonicalFile();
		consoleCurrentPathLabel.setText(currentPath.getAbsolutePath()+" >");
	}

	public void scrollBy(int count) {
		consoleTextPane.scrollBy(count);
	}

	public File getCurrentPath() {
		return currentPath;
	}
}
